package com.mapsolute.map24webservices15.clients.axis.wrappers;

import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.*;

import javax.swing.ImageIcon;
import javax.swing.JFrame;

import com.mapsolute.map24webservices15.clients.axis.stubs.*;

/*
 * The Map24 MGI Service provides methods for requesting binary 
 * map images (bitmaps) and text based image map data (imap/csv).
 *
 * The images generated from Map24 MGI Service always
 * refer to the current state of a Map24 session.
 * This state depends on initial settings and modifications through 
 * Map24 Maplet Remote Control (MRC) commands. The main purpose 
 * of MGI is to return static information after interaction with the Map24 
 * Web Services and without the need for an applet.
 *
 * This is a wrapper class with static methods for the different ways to 
 * issue Map24 MGI Service requests. 
 */
public class Map24MGIWrapper 
{
	
	// ------------------------------------------------------------------------
	//  C o o r d i n a t e 
	// ------------------------------------------------------------------------
	/** 
	 * Helper method for instantiating a Coordinate object.
	 * 
	 * @param longitude  The coordinate's longitude.
	 * @param latitude   The coordinate's latitude.
	 * @return 	         The coordinate.
	 */
	public static Coordinate Coordinate(double longitude, double latitude)
	{
		Coordinate coordinate= new Coordinate();
		coordinate.setLongitude (longitude);
		coordinate.setLatitude  (latitude);
		
		return coordinate;
		
	} // Coordinate

	// ------------------------------------------------------------------------
	//  B i t m a p D e s c r i p t o r s
	// ------------------------------------------------------------------------
	
	/**
	 * Helper method for instantiating a BitmapDescriptor object for an image in GIF format.
	 * 
	 * The BitmapDescriptor is used for setting image attributes such as the mime type,
	 * the size of the image, and the number of colors used in the image.
	 * Map24BitmapRenderEngineWrapper provides helper methods for the following mime types:
	 * <ul>
	 *  <li> image/gif for bitmaps in GIF (Graphics Interchange Format)</li>
	 *  <li> image/png for bitmaps in PNG (Portable  Network graphics) format</li>
	 * </ul>
	 * The default value for the number of colors is 256.
	 * The SetBitmapDescriptorProperty function allows to set additional rendering properties.
	 *
	 * @param width       The image's width.
	 * @param height      The image's height.
	 * @return            The BitmapDescriptor object.
	 */
	public static BitmapDescriptor BitmapDescriptorGIF(int width, int height)
	{
		return BitmapDescriptorGIF(width, height, 256, "image/gif", null);
			
	} // BitmapDescriptor
	
	/** 
	 * Helper method for instantiating a BitmapDescriptor object for an image in PNG format.
	 *
	 * For a detailed description of BitmapDescriptor see BitmapDescriptorGIF().
	 * 
	 * @param width       The image's width.
	 * @param height      The image's height.
	 * @return                The BitmapDescriptor object.
	 */
	public static BitmapDescriptor BitmapDescriptorPNG(int width, int height)
	{
		return BitmapDescriptorGIF(width, height, 256, "image/png", null);
			
	} // BitmapDescriptor
	
		/**
	* Helper method for setting additional rendering properties in the BitmapDescriptor object.
	*
	* For a detailed description of BitmapDescriptor see BitmapDescriptorGIF().
	*
	* The following properties (key-value pairs) are supported:
	* - colortable: The used color model. Possible values: rgb (default), gray, mono
	* - ExpansionStyle: This setting applies if the aspect ratio of the image does not match the 
	*   aspect ratio of the map view stored in the Map24 session and therefore map data required 
	*   for the image is missing in the session's map view. 
	*   Possible values: 
	*     none: The missing map data for the session's map view is retrieved from the server.
	*     mapview: Only the map data contained in the Map24 session is used and the resulting image 
	*     is expanded either vertically or horizontally to match the given image size.
	* - CopyrightLogoDPI: Resolution of the Mapsolute logo in dots per inch. Default value: 72
	* - ScaleBarType: Display mode of the scalebar. For example, you can specify if the text that shows 
	*   the scale and the distance unit is shown above or below the scalebar. Possible values:
	*   0: scalebar is not displayed
	*   1: grey/white scalebar, text above
	*   2: black/white scale bar, text below
	*   3: black/white scale bar, text above 
	*
	* @param descr     The BitmapDescriptor object to set additional properties for.
	* @param key        The property key.
	* @param value      The property value.
	*/
	public static void SetBitmapDescriptorProperty(BitmapDescriptor descr, String key, String value)
	{
		Property[] props= new Property[(descr.getProperties() == null) ? 1 : (1 + descr.getProperties().length)];
		
		for (int i= 1; (i < props.length); i++)
		{
			if (descr.getProperties()[i-1].getKey().equals(key))
			{
				descr.getProperties()[i-1].setValue(value);
				
				return;
			}
			
			props[i]= descr.getProperties()[i-1];
		}
		
		props[0]= new Property();
		props[0].setKey(key);
		props[0].setValue(value);
		
		descr.setProperties(props);
		
	} // SetBitmapDescriptorProperty
	
	
	private static BitmapDescriptor BitmapDescriptorGIF(int width, int height, int noofcolors, String mime, Hashtable propshash)
	{
		BitmapDescriptor bitmapdescriptor = new BitmapDescriptor();
		
		bitmapdescriptor.setImageHeight(height);
		bitmapdescriptor.setImageWidth(width);
		bitmapdescriptor.setNoOfColors(noofcolors);
		
		bitmapdescriptor.setMimeType(BitmapDescriptorMimeType.fromValue(mime));
		
		if (propshash != null)
		{
			Property[] props= new Property[propshash.size()];
			
			int cnt= 0;
			for (Enumeration keys= propshash.keys(); (keys.hasMoreElements()); )
			{
				props[cnt]= new Property();
				
				props[cnt].setKey((String)keys.nextElement());
				props[cnt].setValue((String)propshash.get(props[cnt].getKey()));
				
				cnt+= 1;
			}
			
			bitmapdescriptor.setProperties(props);
			
		} // if (propshash != null)
		
		return bitmapdescriptor;
		
	} // BitmapDescriptor
	
	/** 
	 * Helper method for instantiating a BitmapDescriptor object for an image in JPG format.
	 *
	 * For a detailed description of BitmapDescriptor see BitmapDescriptorGIF().
	 * 
	 * @param width       The image's width.
	 * @param height      The image's height.
	 * @return            The BitmapDescriptor object.
	 */
	public static BitmapDescriptor BitmapDescriptorJPG(int width, int height) {

		BitmapDescriptor bitmapdescriptor = new BitmapDescriptor();
		
		bitmapdescriptor.setImageHeight(height);
		bitmapdescriptor.setImageWidth(width);
								
		return bitmapdescriptor;
		
	}
	

	 private static Map24MGIPortType GetMap24MGIPort(String binding, String map24id, String clientid) throws Exception
	 {
	 	
		Map24MGILocator locator = new Map24MGILocator();
		
		// DEBUG: try to create a port with other URL (e.g. proxy connection)
		if (binding == null)
			return locator.getMap24MGIPort();
		
		java.net.URL url = new java.net.URL(binding+"&sid="+clientid);
		
		Map24MGIPortType port= locator.getMap24MGIPort(url);
		
		com.mapsolute.map24webservices15.clients.axis.stubs.Map24MGIBindingStub stub=
			(com.mapsolute.map24webservices15.clients.axis.stubs.Map24MGIBindingStub)port;
		
			
		
		stub._setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR,  Boolean.FALSE);
		stub._setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);
		stub._setProperty(org.apache.axis.AxisEngine.PROP_SEND_XSI,    Boolean.FALSE);
			
		return port;
			
	 } // GetMap24MGIPort
	

   
	
	// ------------------------------------------------------------------------
	//  R E N D E R    M A P    I M A G E
	// ------------------------------------------------------------------------
	  /**
   	* Renders static bitmap images, passing optional MRC commands in a Vector object.
   	*
   	* It is possible to pass MRC commands to the request. The MRC commands are
   	* processes before rendering the image. In this method it is possible to pass the MRC commands in a Vector object.
   	*
   	* @param binding             The server URL that is assigned to your Map24 ID.
   	* @param map24ID             Your Map24 ID.
   	* @param clientID	           The session ID.
   	* @param commands            Optional MRC commands that are processes before rendering the image.
   	* @param bitmapdescriptor    Optional BitmapDescriptor object for setting image attributes.
   	*/
	 public static RenderBitmapImageResponse RenderBitmapImage(String binding, String map24id, String clientid, Vector commands, BitmapDescriptor bitmapdescriptor)
   {
	 	int cnt= 0;
	 	for (int i= 0; (i < commands.size()); i++)
	 	  if (commands.elementAt(i) instanceof XMLCommandWrapper)
	 	    cnt+= 1;
	 	 
	 	
	 	XMLCommandWrapper[] cmdCommandWrappers= new XMLCommandWrapper[cnt];
	 	cnt= 0;
	 	for (int i= 0; (i < commands.size()); i++)
		 	  if (commands.elementAt(i) instanceof XMLCommandWrapper)
		 	  	cmdCommandWrappers[cnt++]= (XMLCommandWrapper)commands.elementAt(i);
		 	  
		
		return RenderBitmapImage(binding, map24id, clientid, cmdCommandWrappers, bitmapdescriptor);
		
   } // renderMapImage
   
   
    /**
   	* Renders static bitmap images, passing optional MRC commands in an array of type XMLCommandWrapper.
   	*
   	* It is possible to pass MRC commands to the request. The MRC commands are
   	* processes before rendering the image. In this method it is possible to pass the MRC commands in an array of type XMLCommandWrapper.
   	*
   	* @param binding             The server URL that is assigned to your Map24 ID.
   	* @param map24ID             Your Map24 ID.
   	* @param clientID	         The session ID.
   	* @param commands            Optional MRC commands that are processes before rendering the image.
   	* @param bitmapdescriptor    Optional BitmapDescriptor object for setting image attributes.
   	*/
   public static RenderBitmapImageResponse RenderBitmapImage(String binding, String map24id, String clientid, XMLCommandWrapper[] commands, BitmapDescriptor bitmapdescriptor)
   {
		/////////////////////////////////////////////////////		
		// create mapletRemoteControl
		/////////////////////////////////////////////////////		
		Map24MRC mapletRemoteControl = new Map24MRC();
		mapletRemoteControl.setMap24SessionID(clientid);
		mapletRemoteControl.setCommands(commands);
		
		
		/////////////////////////////////////////////////////		
		// create request header
		/////////////////////////////////////////////////////
		RequestHeader requestHeader = new RequestHeader();
		requestHeader.setMap24ID  (map24id);
		requestHeader.setClientID (clientid);
		
		RenderBitmapImageRequest request = new RenderBitmapImageRequest();
		request.setBitmapDescriptor(bitmapdescriptor);
		request.setMRC(mapletRemoteControl);
							
		try 
		{
			return GetMap24MGIPort(binding, map24id, clientid).renderBitmapImage(requestHeader, request);			
		}
		catch(Exception e)
		{
			System.err.println(e);
		}
		
		return null;
		
   } // renderMapImage
   
   /**
   	* Renders static bitmap images.
   	*
   	* This method does not allow to send MRC commands in the request.
   	*
   	* @param binding             The server URL that is assigned to your Map24 ID.
   	* @param map24ID             Your Map24 ID.
   	* @param clientID	         	 The session ID.
   	* @param commands            Optional MRC commands that are processes before rendering the image.
   	* @param bitmapdescriptor    Optional BitmapDescriptor object for setting image attributes.
   	*/
   public static RenderBitmapImageResponse RenderBitmapImage(String binding, String map24id, String clientid, BitmapDescriptor bitmapdescriptor)
   {
		/////////////////////////////////////////////////////		
		// create mapletRemoteControl
		/////////////////////////////////////////////////////		
		Map24MRC mapletRemoteControl = new Map24MRC();
		mapletRemoteControl.setMap24SessionID(clientid);
			
		
		/////////////////////////////////////////////////////		
		// create request header
		/////////////////////////////////////////////////////
		RequestHeader requestHeader = new RequestHeader();
		requestHeader.setMap24ID  (map24id);
		requestHeader.setClientID (clientid);
		
		RenderBitmapImageRequest request = new RenderBitmapImageRequest();
		
		request.setBitmapDescriptor(bitmapdescriptor);
		request.setMRC(mapletRemoteControl);
	
							
		try 
		{
			return GetMap24MGIPort(binding, map24id, clientid).renderBitmapImage(requestHeader, request);			
		}
		catch(Exception e)
		{
			System.err.println(e);
		}
		
		return null;
		
   } // renderMapImage
   
   
	// ----------------------------------------------------	
	//  D i s p l a y   M a p I m a g e
	// ----------------------------------------------------	
   	/**
	   * Helper method for showing a given bitmap image in a frame.
	   *
	   * This method can be used to show the resulting bitmap image returned in a renderMapImage operation in an instance of JFrame.
	   *
	   * @param imageData     A byte array containing the image data.
	   * @param width         The desired image width.
	   * @param height        The desired image height.
	   * @param title         The title of the image. The title is shown in the title bar of the frame.
	   */
	   public static void DisplayMapImage(byte[] imageData, final int width, final int height, String title)
	   {
		   	try 
		   	{	final Image image=	new ImageIcon(imageData).getImage();
		   		
		   		JFrame frame=	new JFrame(title);
		   		frame.getContentPane().add(new Canvas(){
		   			
					private static final long serialVersionUID = 1L;

					public void paint(Graphics g){
		   				g.drawImage(image, 0, 0, width, height, null);
		   			}
		   		});
		   		frame.setSize(width, height+20);
		   		frame.setVisible(true);
		   		frame.addWindowListener(new WindowAdapter(){
		   			public void windowClosing(WindowEvent we){
		   				System.exit(0);
		   			}
		   		});
		   	}
		   	catch(Exception e)
		   	{
		   		System.err.println(e);
		   	}
	   	
	   } // DisplayMapImage
	   
   
	   public static void DisplayMapImage(RenderBitmapImageResponse response, String title)
	   {
	   		DisplayMapImage(response.getBitmapData(), response.getBitmapDescriptor().getImageWidth(), response.getBitmapDescriptor().getImageHeight(), title);
	   	
	   } // DisplayMapImage

	
   

} // Map24BitmapRenderEngineWrapper
